package methodRef;


import mybatis.SerializableFunction;
import mybatis.Student;

import java.beans.Introspector;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/**
 * 〈〉
 *
 * @author coach tam
 * @email 327395128@qq.com
 * @create 2023/10/17
 * @since 1.0.0
 * 〈坚持灵活 灵活坚持〉
 */
public class MethodRefTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 语法：ClassName::staticMethodName
       /* Function<Double, Long> square = Math::round;
        Long apply = square.apply(1.2);
        System.out.println(apply);

        // 语法：objectReference::instanceMethodName
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.forEach(System.out::println);*/

//        testInstanceMethodRef1();
        //方法引用
        SerializableFunction<Student, String> function = Student::getName;
        // 第1步 获取SerializedLambda
        Method method = function.getClass().getDeclaredMethod("writeReplace");
        method.setAccessible(Boolean.TRUE);
        SerializedLambda serializedLambda = (SerializedLambda) method.invoke(function);
        // 第2步 implMethodName 即为Field对应的Getter方法名
        String implMethodName = serializedLambda.getImplMethodName();
        String fieldName = null;
        if (implMethodName.startsWith("get") && implMethodName.length() > 3) {
            fieldName = Introspector.decapitalize(implMethodName.substring(3));
        } else if (implMethodName.startsWith("is") && implMethodName.length() > 2) {
            fieldName = Introspector.decapitalize(implMethodName.substring(2));
        }
        System.out.println(fieldName);
    }
    public static void testInstanceMethodRef1() {
        //匿名类
        BiFunction<Student, Integer, String> f1 = new BiFunction<Student, Integer, String>() {
            @Override
            public String apply(Student student, Integer s) {
                return student.getStatus(s);
            }
        };

        //lambda
        BiFunction<Student, Integer, String> f2 = (student, s) -> student.getStatus(s);

        //method reference
        BiFunction<Student, Integer, String> f3 = Student::getStatus;

        System.out.println(getStudentStatus(new Student("erGouWang", 18), 1, f3));


    }
    private static String getStudentStatus(Student student, Integer action, BiFunction<Student, Integer, String> biFunction) {
        return biFunction.apply(student, action);
    }


    public void testConstructorMethodRef() {
        BiFunction<String, Integer, Student> s1 = new BiFunction<String, Integer, Student>() {
            @Override
            public Student apply(String name, Integer age) {
                return new Student(name, age);
            }
        };

        //lambda表达式
        BiFunction<String, Integer, Student> s2 = (name, age) -> new Student(name, age);

        //对应的方法引用
        BiFunction<String, Integer, Student> s3 = Student::new;

        //使用
        System.out.println(getStudent("cuiHuaNiu", 20, s3).toString());
    }

    private Student getStudent(String name, int age, BiFunction<String, Integer, Student> biFunction) {
        return biFunction.apply(name, age);
    }



    public static void testInstanceMethodRef2() {
        PrintUtils printUtils = new PrintUtils();
        //匿名类
        Consumer<Student> c1 = new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                printUtils.printStudent(student);
            }
        };

        //Lambda表达式
        Consumer<Student> c2 = student -> printUtils.printStudent(student);

        //方法引用
        Consumer<Student> c3 = printUtils::printStudent;

        //使用
        consumeStudent(new Student("andy"), printUtils::printStudentHashCode);
    }

    private static void consumeStudent(Student student, Consumer<Student> consumer) {
        consumer.accept(student);
    }



}
